package handler

import (
	"errors"
	"net/http"
	"ruoyi-go-echo-ddd/internal/application"
	"ruoyi-go-echo-ddd/internal/domain/model"
	"ruoyi-go-echo-ddd/internal/infrastructure/http/request"
	"ruoyi-go-echo-ddd/internal/infrastructure/http/response"
	"ruoyi-go-echo-ddd/internal/infrastructure/utils"

	"github.com/labstack/echo/v4"
	"github.com/rs/zerolog"
	"github.com/spf13/cast"
)

// SysMenuHandler 系统菜单控制器
type SysMenuHandler struct {
	menuApp  *application.SysMenuApplication
	tokenApp *application.TokenApplication
}

// NewSysMenuHandler 系统菜单控制器初始化
func NewSysMenuHandler(m *application.SysMenuApplication, t *application.TokenApplication) *SysMenuHandler {
	return &SysMenuHandler{
		menuApp:  m,
		tokenApp: t,
	}
}

// SaveHandler 保存
// @Summary 新增菜单
// @Description 创建新的菜单信息
// @Tags 菜单管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param sysMenu body model.SysMenu true "菜单信息"
// @Success 200 {object} response.Result{data=model.SysMenu} "新增成功"
// @Failure 400 {object} response.Result "参数解析错误"
// @Failure 500 {object} response.Result "服务器错误"
// @Router /system/menu [post]
func (controller *SysMenuHandler) SaveHandler(e echo.Context) error {
	var sysMenu *model.SysMenu
	if err := e.Bind(&sysMenu); err != nil {
		response.NewRespCodeMsg(e, 500, "系统菜单新增参数解析错误")
		return err
	}

	result, err := controller.menuApp.Insert(e, sysMenu)
	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}

	response.NewResponse(e, 200, "新增成功", result)
	return nil
}

// UpdateHandler 更新
// @Summary 更新菜单
// @Description 修改菜单信息
// @Tags 菜单管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param sysMenu body model.SysMenu true "菜单信息"
// @Success 200 {object} response.Result{data=int64} "修改成功"
// @Failure 400 {object} response.Result "参数解析错误"
// @Failure 500 {object} response.Result "服务器错误"
// @Router /system/menu [put]
func (controller *SysMenuHandler) UpdateHandler(e echo.Context) error {
	var sysMenu *model.SysMenu
	if err := e.Bind(&sysMenu); err != nil {
		response.NewRespCodeMsg(e, 500, "系统菜单更新参数解析错误")
		return err
	}

	if sysMenu.Id == 0 {
		response.NewRespCodeMsg(e, 500, "系统菜单ID不能为空")
		return errors.New("系统菜单ID不能为空")
	}

	result, err := controller.menuApp.Update(e, sysMenu)
	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}
	response.NewResponse(e, 200, "系统菜单信息更新成功", result)
	return nil
}

// BatchSaveHandler 批量新增
// @Summary 批量新增菜单
// @Description 批量新增菜单
// @Tags 菜单管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param list body []model.SysMenu true "菜单信息"
// @Success 200 {object} response.Result{data=int64} "批量新增成功"
// @Failure 400 {object} response.Result "参数解析错误"
// @Failure 500 {object} response.Result "服务器错误"
// @Router /system/menu/batchSave [post]
func (controller *SysMenuHandler) BatchSaveHandler(e echo.Context) error {
	var list []*model.SysMenu
	if err := BindParam(e, &list); err != nil {
		response.NewRespCodeMsg(e, 500, "系统菜单批量新增参数解析错误")
		return err
	}

	result, err := controller.menuApp.BatchInsert(e, list)
	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}

	response.NewResponse(e, 200, "系统菜单批量新增成功", result)
	return nil
}

// SelectTreeTableListHandler 不分页树型菜单
// @Summary 不分页树型菜单
// @Description 查询不分页树型菜单数据
// @Tags 菜单管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param req query request.MenuPageParam false "菜单信息"
// @Success 200 {object} response.Result{data=[]model.SysMenu} "查询成功"
// @Failure 400 {object} response.Result "参数解析错误"
// @Failure 500 {object} response.Result "服务器错误"
// @Router /system/menu/list [get]
func (controller *SysMenuHandler) SelectTreeTableListHandler(e echo.Context) error {
	zerolog.DefaultContextLogger.Info().Msgf("context类型===%s", e.QueryParam("menuStatus"))
	req := new(request.MenuPageParam)
	if err := BindParam(e, req); err != nil {
		response.NewRespCodeMsg(e, http.StatusInternalServerError, "菜单表格树参数解析失败")
		return err
	}
	zerolog.DefaultContextLogger.Info().Msgf("菜单表格树查询入参===\n%s", utils.ToJsonFormat(req))

	loginUser, err := controller.tokenApp.GetLoginUser(e)
	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}

	if loginUser != nil {
		req.UserId = loginUser.UserId
	}

	list, err := controller.menuApp.SelectList(e, req)
	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}

	response.NewResponse(e, 200, "查询成功", list)
	return nil
}

type SysMenuPage struct {
	Content []model.SysMenu `json:"content"`
	Records int64           `json:"records,string"`
	Pages   int64           `json:"pages,string"`
}

// SelectPageHandler 分页
// @Summary 菜单分页
// @Description 查询菜单分页
// @Tags 菜单管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param req query request.MenuPageParam false "菜单信息"
// @Success 200 {object} response.Result{data=SysMenuPage} "查询成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/menu/page [get]
func (controller *SysMenuHandler) SelectPageHandler(e echo.Context) error {
	req := new(request.MenuPageParam)
	if err := BindParam(e, req); err != nil {
		response.NewRespCodeMsg(e, http.StatusInternalServerError, "菜单分页参数解析失败")
		return err
	}
	zerolog.DefaultContextLogger.Info().Msgf("菜单分页查询入参===\n%s", utils.ToJsonFormat(req))

	list, total, page, err := controller.menuApp.SelectPage(e, req)
	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}

	response.NewResponse(e, 200, "系统公告分页查询成功", response.NewPageData(list, total, page))
	return nil
}

// SelectOneHandler 查询
// @Summary 菜单查询
// @Description 通过主键ID查询
// @Tags 菜单管理
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param id path string true "菜单主键ID"
// @Success 200 {object} response.Result{data=model.SysMenu} "查询成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/menu/{id} [get]
func (controller *SysMenuHandler) SelectOneHandler(e echo.Context) error {
	id, err := GetSinglePathParam(e, "id")
	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}

	data, err := controller.menuApp.SelectById(e, cast.ToInt64(id))
	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}

	response.NewResponse(e, 200, "查询成功", data)
	return nil
}

// BatchDeleteHandler 批量删除
// @Summary 菜单批量删除
// @Description 菜单批量删除
// @Tags 菜单管理
// @Accept application/json; charset=UTF-8
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param id path string true "英文逗号分割的主键ID"
// @Success 200 {object} response.Result{data=int64} "删除成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/menu/{id} [delete]
func (controller *SysMenuHandler) BatchDeleteHandler(e echo.Context) error {
	ids, err := GlobalDeleteHandler(e, "id")
	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}

	count, err := controller.menuApp.BatchDelete(e, ids)
	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}
	response.NewResponse(e, 200, "批量删除成功", count)
	return nil
}

// TreeSelectHandler 菜单下拉树列表
// @Summary 菜单下拉树列表
// @Description 查询菜单下拉树列表
// @Tags 菜单管理
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Success 200 {object} response.Result{data=[]model.TreeSelect} "查询成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/menu/treeSelect [get]
func (controller *SysMenuHandler) TreeSelectHandler(e echo.Context) error {
	loginUser, err := controller.tokenApp.GetLoginUser(e)
	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}

	menuList, err := controller.menuApp.SelectListByMenuAndUserId(e, &model.SysMenu{}, loginUser.UserId)

	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}

	response.NewResponse(e, http.StatusOK, "查询成功", controller.menuApp.BuildMenuTreeSelect(menuList))
	return nil
}

// RoleMenuTreeRoleIdHandler 角色菜单列表树
// @Summary 角色菜单列表树
// @Description 通过角色ID查询对应菜单列表树
// @Tags 菜单管理
// @Produce application/json; charset=UTF-8
// @Security ApiKeyAuth
// @Param roleId path string true "角色ID"
// @Success 200 {object} response.Result{data=model.RoleMenuTreeSelect} "查询成功"
// @Failure 500 {object} response.Result "参数解析错误"
// @Router /system/menu/roleMenuTreeSelect/{roleId} [get]
func (controller *SysMenuHandler) RoleMenuTreeRoleIdHandler(e echo.Context) error {
	roleId, err := GetSinglePathParam(e, "roleId")
	if err != nil {
		response.NewRespCodeMsg(e, 500, "角色ID不能为空")
		return errors.New("角色ID不能为空")
	}

	loginUser, err := controller.tokenApp.GetLoginUser(e)
	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}
	roleMenuTreeSelect, err := controller.menuApp.BuildRoleMenuTreeSelect(e, loginUser.UserId, cast.ToInt64(roleId))
	if err != nil {
		response.NewRespCodeErr(e, 500, err)
		return err
	}
	response.NewResponse(e, http.StatusOK, "查询成功", roleMenuTreeSelect)
	return nil
}
